/******************************************
 * AUTHOR:          Rector
 * CREATEDON:       2018-09-26
 * OFFICIAL_SITE:    码友网(https://codedefault.com)--专注.NET/.NET Core
 * 版权所有，请勿删除
 ******************************************/

using AutoMapper;
using DncZeus.Api.Entities;
using DncZeus.Api.Entities.QueryModels;
using DncZeus.Api.Extensions;
using DncZeus.Api.Extensions.AuthContext;
using DncZeus.Api.Extensions.DataAccess;
using DncZeus.Api.ViewModels.Rbac.DncMenu;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using static DncZeus.Api.Entities.Enums.CommonEnum;

namespace DncZeus.Api.Controllers
{
    /// <summary>
    /// 
    /// </summary>
    [Route("api/v1/[controller]/[action]")]
    [ApiController]
    [Authorize]
    public class AccountController : ControllerBase
    {
        private readonly DncZeusDbContext _dbContext;
        private readonly IMapper _mapper;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbContext"></param>
        public AccountController(DncZeusDbContext dbContext, IMapper mapper)
        {
            _dbContext = dbContext;
            _mapper = mapper;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Profile()
        {
            var response = ResponseModelFactory.CreateInstance;
            using (_dbContext)
            {
                var guid = AuthContextService.CurrentUser.Guid;
                var user = _dbContext.DncUser.FirstOrDefaultAsync(x => x.Guid == guid).Result;

                var menus = _dbContext.DncMenu.Where(x => x.IsDeleted == IsDeleted.No && x.Status == Status.Normal).ToList();

                //                //查询当前登录用户拥有的权限集合(非超级管理员)
                //                var sqlPermission = @"SELECT P.Code AS PermissionCode,P.ActionCode AS PermissionActionCode,P.Name AS PermissionName,P.Type AS PermissionType,M.Name AS MenuName,M.Guid AS MenuGuid,M.Alias AS MenuAlias,M.IsDefaultRouter FROM DncRolePermissionMapping AS RPM 
                //LEFT JOIN DncPermission AS P ON P.Code = RPM.PermissionCode
                //INNER JOIN DncMenu AS M ON M.Guid = P.MenuGuid
                //WHERE P.IsDeleted=0 AND P.Status=1 AND EXISTS (SELECT 1 FROM DncUserRoleMapping AS URM WHERE URM.UserGuid=@UserGuid AND URM.RoleCode=RPM.RoleCode)";
                //                if (user.UserType == UserType.SuperAdministrator)
                //                {
                //                    //如果是超级管理员
                //                    sqlPermission = @"SELECT P.Code AS PermissionCode,P.ActionCode AS PermissionActionCode,P.Name AS PermissionName,P.Type AS PermissionType,M.Name AS MenuName,M.Guid AS MenuGuid,M.Alias AS MenuAlias,M.IsDefaultRouter FROM DncPermission AS P 
                //INNER JOIN DncMenu AS M ON M.Guid = P.MenuGuid
                //WHERE P.IsDeleted=0 AND P.Status=1";
                //                }


                var userGuid = AuthContextService.CurrentUser.Guid;

                var query = from rpm in _dbContext.DncRolePermissionMapping
                            join p in _dbContext.DncPermission on rpm.PermissionCode equals p.Code
                            join m in _dbContext.DncMenu on p.MenuGuid equals m.Guid
                            where p.IsDeleted == IsDeleted.No && p.Status == Status.Normal && _dbContext.DncUserRoleMapping
                                .Any(urm => urm.UserGuid == userGuid && urm.RoleCode == rpm.RoleCode)
                            select new DncPermissionWithMenu
                            {
                                PermissionCode = p.Code,
                                PermissionActionCode = p.ActionCode,
                                PermissionName = p.Name,
                                PermissionType = p.Type,
                                MenuName = m.Name,
                                MenuGuid = m.Guid,
                                MenuAlias = m.Alias,
                                IsDefaultRouter = m.IsDefaultRouter
                            };

                if (AuthContextService.CurrentUser.IsSupperAdministrator)
                {
                    query = from p in _dbContext.DncPermission
                            join m in _dbContext.DncMenu on p.MenuGuid equals m.Guid
                            where p.IsDeleted == IsDeleted.No && p.Status == Status.Normal
                            select new DncPermissionWithMenu
                            {
                                PermissionCode = p.Code,
                                PermissionActionCode = p.ActionCode,
                                PermissionName = p.Name,
                                PermissionType = p.Type,
                                MenuName = m.Name,
                                MenuGuid = m.Guid,
                                MenuAlias = m.Alias,
                                IsDefaultRouter = m.IsDefaultRouter
                            };
                }


                var permissions = query.ToList();

                var pagePermissions = permissions.GroupBy(x => x.MenuAlias).ToDictionary(g => g.Key, g => g.Select(x => x.PermissionActionCode).Distinct());
                response.SetData(new
                {
                    access = new string[] { },
                    avator = user.Avatar,
                    user_guid = user.Guid,
                    user_name = user.DisplayName,
                    user_type = user.UserType,
                    permissions = pagePermissions

                });
            }

            return Ok(response);
        }

        private List<string> FindParentMenuAlias(List<DncMenuQueryModel> menus, Guid? parentGuid)
        {
            var pages = new List<string>();
            var parent = menus.FirstOrDefault(x => x.Guid == parentGuid);
            if (parent != null)
            {
                if (!pages.Contains(parent.Alias))
                {
                    pages.Add(parent.Alias);
                }
                else
                {
                    return pages;
                }
                if (parent.ParentGuid != Guid.Empty)
                {
                    pages.AddRange(FindParentMenuAlias(menus, parent.ParentGuid));
                }
            }

            return pages.Distinct().ToList();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Menu()
        {
            /*
             SELECT M.* FROM DncRolePermissionMapping AS RPM 
LEFT JOIN DncPermission AS P ON P.Code = RPM.PermissionCode
INNER JOIN DncMenu AS M ON M.Guid = P.MenuGuid
WHERE P.IsDeleted=0 AND P.Status=1 AND P.Type=0 AND M.IsDeleted=0 AND M.Status=1 AND EXISTS (SELECT 1 FROM DncUserRoleMapping AS URM WHERE URM.UserGuid=@UserGuid AND URM.RoleCode=RPM.RoleCode)
             */

            /*
             from drp in _dbContext.DncRolePermissionMapping
                        join p in _dbContext.DncPermission on drp.PermissionCode equals p.Code
                        join m in _dbContext.DncMenu on p.MenuGuid equals m.Guid
                        where p.IsDeleted == IsDeleted.No && p.Status == Status.Normal && p.Type == PermissionType.Menu &&
                              m.IsDeleted == IsDeleted.No && m.Status == Status.Normal && _dbContext.DncUserRoleMapping
                                  .Any(urm => urm.UserGuid == userGuid && urm.RoleCode == drp.RoleCode)
             */

            var userGuid = AuthContextService.CurrentUser.Guid;

            var query = from rpm in _dbContext.DncRolePermissionMapping
                        join p in _dbContext.DncPermission on rpm.PermissionCode equals p.Code into perm
                        from subperm in perm.DefaultIfEmpty()
                        join m in _dbContext.DncMenu on subperm.MenuGuid equals m.Guid
                        where subperm.IsDeleted == IsDeleted.No && subperm.Status == Status.Normal && subperm.Type == PermissionType.Menu && m.IsDeleted == IsDeleted.No && m.Status == Status.Normal
                              && _dbContext.DncUserRoleMapping.Any(urm => urm.UserGuid == userGuid && urm.RoleCode == rpm.RoleCode)
                        select new DncMenuQueryModel
                        {
                            Alias = m.Alias,
                            BeforeCloseFun = m.BeforeCloseFun,
                            Component = m.Component,
                            Guid = m.Guid,
                            ParentGuid = m.ParentGuid,
                            Sort = m.Sort,
                            IsDefaultRouter = (int)m.IsDefaultRouter,
                            HideInMenu = (int)m.HideInMenu,
                            Icon = m.Icon,
                            Name = m.Name,
                            NotCache = (int)m.NotCache,
                            Url = m.Url
                        };

            if (AuthContextService.CurrentUser.IsSupperAdministrator)
            {
                //如果是超级管理员
                //@"SELECT * FROM DncMenu WHERE IsDeleted=0 AND Status=1";
                query = from m in _dbContext.DncMenu
                        where m.IsDeleted == IsDeleted.No && m.Status == Status.Normal
                        select new DncMenuQueryModel
                        {
                            Alias = m.Alias,
                            BeforeCloseFun = m.BeforeCloseFun,
                            Component = m.Component,
                            Guid = m.Guid,
                            ParentGuid = m.ParentGuid,
                            Sort = m.Sort,
                            IsDefaultRouter = (int)m.IsDefaultRouter,
                            HideInMenu = (int)m.HideInMenu,
                            Icon = m.Icon,
                            Name = m.Name,
                            NotCache = (int)m.NotCache,
                            Url = m.Url
                        };
            }
            var menus = query.ToList();
            var rootMenus = _dbContext.DncMenu.Where(x => x.IsDeleted == IsDeleted.No && x.Status == Status.Normal && x.ParentGuid == Guid.Empty).ToList();
            foreach (var root in rootMenus)
            {
                if (menus.Exists(x => x.Guid == root.Guid))
                {
                    continue;
                }
                menus.Add(_mapper.Map<DncMenu, DncMenuQueryModel>(root));
            }
            menus = menus.OrderBy(x => x.Sort).ThenBy(x => x.CreatedOn).ToList();
            var menu = MenuItemHelper.LoadMenuTree(menus, "0");
            return Ok(menu);
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public static class MenuItemHelper
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="menus"></param>
        /// <param name="selectedGuid"></param>
        /// <returns></returns>
        public static List<MenuItem> BuildTree(this List<MenuItem> menus, string selectedGuid = null)
        {
            var lookup = menus.ToLookup(x => x.ParentId);

            List<MenuItem> Build(string pid)
            {
                return lookup[pid]
                    .Select(x => new MenuItem()
                    {
                        Guid = x.Guid,
                        ParentId = x.ParentId,
                        Children = Build(x.Guid),
                        Component = x.Component ?? "Main",
                        Name = x.Name,
                        Path = x.Path,
                        Meta = new MenuMeta
                        {
                            BeforeCloseFun = x.Meta.BeforeCloseFun,
                            HideInMenu = x.Meta.HideInMenu,
                            Icon = x.Meta.Icon,
                            NotCache = x.Meta.NotCache,
                            Title = x.Meta.Title,
                            Permission = x.Meta.Permission
                        }
                    }).ToList();
            }

            var result = Build(selectedGuid);
            return result;
        }

        public static List<MenuItem> LoadMenuTree(List<DncMenuQueryModel> menus, string selectedGuid = null)
        {
            var temp = menus.Select(x => new MenuItem
            {
                Guid = x.Guid.ToString(),
                ParentId = x.ParentGuid != null && ((Guid)x.ParentGuid) == Guid.Empty ? "0" : x.ParentGuid?.ToString(),
                Name = x.Alias,
                Path = $"/{x.Url}",
                Component = x.Component,
                Meta = new MenuMeta
                {
                    BeforeCloseFun = x.BeforeCloseFun ?? "",
                    HideInMenu = x.HideInMenu == 1,
                    Icon = x.Icon,
                    NotCache = x.NotCache == 1,
                    Title = x.Name
                }
            }).ToList();
            var tree = temp.BuildTree(selectedGuid);
            return tree;
        }
    }
}